import G6 from '@antv/g6';
import { forEach, groupBy } from 'lodash';

// register custom layout
G6.registerLayout('custom-layout', {
    // 默认参数
    getDefaultCfg() {
        return {};
    },
    // 执行布局
    execute() {
        const self = this;
        const nodes = self.nodes,
            combos = self.combos;
        if (!nodes?.length) {
            return;
        }

        const edges = self.edges || [];
        const nodeMap = {};
        nodes.forEach(n => nodeMap[n.id] = n);
        const comboWidth = 164, comboHeight = 54, wSpace = 46, hSpace = 48;
        // 根据层级将combos分组
        let groupCombos = groupBy(combos, 'level');

        // 将没有调用关系的combo分离出来
        const selfCombos = groupCombos[-1] || [];
        const selfMax = Math.ceil(Math.sqrt(selfCombos.length));
        delete groupCombos[-1];
        let maxLevelCount = 0;  // combo数量最多的层级中combo数量
        forEach(groupCombos, c => {
            if (c.length > maxLevelCount) {
                maxLevelCount = c.length;
            }
        })

        let comboNodes = [];
        forEach(groupCombos, (tempCombos, h) => {
            forEach(tempCombos, (combo, i) => {
                const nodeNum = combo.children.length;
                const nodeMax = Math.ceil(Math.sqrt(nodeNum));
                comboNodes.push({
                    id: combo.id,
                    x: 20 + (comboWidth + wSpace) * ((maxLevelCount - tempCombos.length) / 2 + i),
                    y: 20 + h * (comboHeight + hSpace),
                    width: comboWidth,
                    height: comboHeight,
                    combo,
                    max: nodeMax,
                })
            })
        })
        forEach(selfCombos, (combo, i) => {
            const nodeNum = combo.children.length;
            const nodeMax = Math.ceil(Math.sqrt(nodeNum));

            comboNodes.push({
                id: combo.id,
                x: 20 + (comboWidth + wSpace) * (maxLevelCount + Math.floor(i % selfMax)),
                y: 20 + Math.floor(i / selfMax) * (comboHeight + hSpace),
                width: comboWidth,
                height: comboHeight,
                combo,
                max: nodeMax,
            })
        })

        comboNodes.forEach(c => {
            const {
                x,
                y,
                combo,
                width,
                height
            } = c;
            const x0 = x - width / 2;
            const y0 = y - height / 2;
            combo.children.forEach((n, i) => {
                const node = nodeMap[n.id];
                node.x = x0;
                node.y = y0;
                // node.x = node.xaxis;
                // node.y = node.yaxis;
            });
            combo.x = x;
            combo.y = y;
            // combo.x = combo.xaxis;
            // combo.y = combo.yaxis;
        })

        if (this.onLayoutEnd) {
            this.onLayoutEnd();
        }
        return {
            nodes: nodes,
            edges: edges,
        };
    },
});

// register custom merge layout
G6.registerLayout('custom-merge-layout', {
    // 默认参数
    getDefaultCfg() {
        return {
            nodeWidth: 220,
            nodeHeight: 122,
            wSpace: 46,
            hSpace: 48,
            comboOffsetX: 0,
            comboOffsetY: 0,
        };
    },
    // 执行布局
    execute() {
        const self = this;
        const { nodes, edges, combos, nodeWidth, nodeHeight, wSpace, hSpace, comboOffsetX, comboOffsetY } = self;
        if (!nodes?.length) {
            return;
        }

        const noComboNodes = [];
        const nodeMap = {};
        nodes.forEach(n => {
            if (!n.comboId) {
                noComboNodes.push(n);
            }
            nodeMap[n.id] = n;
        });

        const comboWidth = 164, comboHeight = 70;
        // 没有comboId的节点网格布局，每行个数
        const nodeMax = Math.ceil(Math.sqrt(noComboNodes.length));
        forEach(noComboNodes, (n, i) => {
            const node = nodeMap[n.id];
            node.x = node.xaxis;
            node.y = node.yaxis;
            // node.x = (nodeWidth + wSpace) * (i % nodeMax);
            // node.y = (nodeHeight + hSpace) * (Math.floor(i / nodeMax));
        })
        // 有comboId的节点，combo之间网格布局，每行combo个数
        const comboMax = Math.ceil(Math.sqrt(combos.length));
        forEach(combos, (combo, i) => {
            const x = comboOffsetX + (nodeWidth + wSpace) * nodeMax + (comboWidth + wSpace) * Math.floor(i % comboMax);
            const y = comboOffsetY + Math.floor(i / comboMax) * (comboHeight + hSpace);
            combo.children.forEach((n) => {
                const node = nodeMap[n.id];
                node.x = node.xaxis;
                // node.x = x;
                // node.y = y;
                node.y = node.yaxis;
            });
            combo.x = x;
            combo.y = y;
        })

        if (this.onLayoutEnd) {
            this.onLayoutEnd();
        }

        return {
            nodes: nodes,
            edges: edges,
        };
    },

    layout(data) {
        const self = this;
        self.init(data);
        self.execute();
    }
});
